home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Science / RasMol2 / render.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-28  |  49.7 KB  |  2,094 lines  |  [TEXT/KAHL]

  1. /* render.c
  2.  * RasMol2 Molecular Graphics
  3.  * Roger Sayle, October 1994
  4.  * Version 2.5
  5.  */
  6. #include "rasmol.h"
  7.  
  8. #ifdef IBMPC
  9. #include <windows.h>
  10. #include <malloc.h>
  11. #endif
  12. #ifdef APPLEMAC
  13. #ifdef __CONDITIONALMACROS__
  14. #include <Printing.h>
  15. #else
  16. #include <PrintTraps.h>
  17. #endif
  18. #include <Types.h>
  19. #endif
  20. #ifndef sun386
  21. #include <stdlib.h>
  22. #endif
  23.  
  24. #include <string.h>
  25. #include <stdio.h>
  26. #include <math.h>
  27.  
  28. #define RENDER
  29. #include "graphics.h"
  30. #include "render.h"
  31. #include "molecule.h"
  32. #include "transfor.h"
  33. #include "command.h"
  34. #include "abstree.h"
  35. #include "pixutils.h"
  36.  
  37. /* Avoid PowerPC Errors! */
  38. #ifdef INFINITY
  39. #undef INFINITY
  40. #endif
  41.  
  42. #define PoolSize        16
  43. #define RootSix         2.4494897427831780
  44. #define OneOverRootSix  0.4082482904638630
  45. #define TwoOverRootSix  0.8164965809277260
  46. #define ApproxZero      1.0E-3
  47. #define INFINITY       200000
  48. #define FUDGEFACTOR    1000
  49.  
  50.  
  51.  
  52. typedef struct { int dx, dy, dz; } DotVector;
  53. typedef struct { 
  54.     DotVector __far *probe;
  55.     DotVector __far *dots;
  56.     int count;
  57.     } ElemDotStruct;
  58.  
  59. typedef struct _Item {
  60.     struct _Item __far *list;
  61.     Atom  __far *data;
  62.     } Item;
  63.  
  64. typedef struct { Real h,l; } Interval;
  65.  
  66.  
  67. static ElemDotStruct __far *ElemDots;
  68. static Label *FreeLabel, *LabelList;
  69. static Atom __far * __far *YBucket;
  70. static Atom __far * __far *IBuffer;
  71. static int BuckY,ItemX;
  72. static int FBufX,FBufY;
  73. static int DBClear;
  74.  
  75. static Atom __far *SBuffer;
  76. static Atom __far *Exclude;
  77. static Real ShadowI, ShadowJ, ShadowK;
  78. static int  ShadowX, ShadowY, ShadowZ;
  79. static int deltax, deltay, deltaz;
  80. static int xcord, ycord, zcord;
  81. static int xflag, yflag, zflag;
  82. static int xhash, yhash, zhash;
  83. static int RayCount;
  84.  
  85. static Item __far *FreeItem;
  86. static Real VoxRatio,IVoxRatio;
  87. static int VoxelCount,InVoxCount;
  88. static int ProbeCount;
  89. static int VoxelsDone;
  90.  
  91. /* Identified Atom Info */
  92. static Long IdentDist;
  93. static int IdentFound;
  94. static int IdentDepth;
  95.  
  96.  
  97. /* Macros for commonly used loops */
  98. #define ForEachAtom  for(chain=Database->clist;chain;chain=chain->cnext) \
  99.              for(group=chain->glist;group;group=group->gnext)    \
  100.              for(aptr=group->alist;aptr;aptr=aptr->anext)
  101. #define ForEachBond  for(bptr=Database->blist;bptr;bptr=bptr->bnext)
  102. #define ForEachBack  for(chain=Database->clist;chain;chain=chain->cnext) \
  103.              for(bptr=chain->blist;bptr;bptr=bptr->bnext)
  104.  
  105.  
  106.  
  107.  
  108. static void FatalRenderError(ptr)
  109.     char *ptr;
  110. {
  111.     char buffer[80];
  112.  
  113.     sprintf(buffer,"Renderer Error: Unable to allocate %s!",ptr);
  114.     RasMolFatalExit(buffer);
  115. }
  116.  
  117.  
  118. int isqrt( val )
  119.     Card val;
  120. {
  121. #ifndef sun386
  122.     register int i,result;
  123.     register Card side, left;
  124.     register Card temp;
  125.  
  126.     result = 0;
  127.     side = left = 0;
  128.     for( i=0; i<sizeof(Card)*4; i++ )
  129.     {   left = (left<<2) + (val>>30);
  130.     result <<= 1; side <<= 1;
  131.     temp = side | 1;
  132.     val <<= 2;
  133.  
  134.     if( left >= temp )
  135.     {   side = temp+1;
  136.         left -= temp;
  137.         result |= 1;
  138.     }
  139.     }
  140.     return( (int)result );
  141. #else
  142.     return( (int)sqrt((double)val) );
  143. #endif
  144. }
  145.  
  146. #ifdef IBMPC
  147. void ClearBuffers()
  148. {
  149.     register char __huge *ptr;
  150.     register Long count;
  151.  
  152.     if( !FBClear )
  153.     {   FBClear = True;
  154.     ptr = (Pixel __huge*)GlobalLock(FBufHandle);
  155.     count = (Long)XRange*YRange;
  156.     while( count > 65534 )
  157.     {   _fmemset(ptr,0,(size_t)65534);
  158.         count -= 65534;
  159.         ptr += 65534;
  160.     }
  161.     if( count )
  162.         _fmemset(ptr,0,(size_t)count);
  163.     GlobalUnlock(FBufHandle);
  164.     }
  165.  
  166.     if( !DBClear )
  167.     {   DBClear = True;
  168.     ptr = (char __huge*)GlobalLock(DBufHandle);
  169.     count = (Long)XRange*YRange*sizeof(short);
  170.     while( count > 65534 )
  171.     {   _fmemset(ptr,0,(size_t)65534);
  172.         count -= 65534;
  173.         ptr += 65534;
  174.     }
  175.     if( count )
  176.         _fmemset(ptr,0,(size_t)count);
  177.     GlobalUnlock(DBufHandle);
  178.     }
  179. }
  180. #else /* !IBMPC */
  181. void ClearBuffers()
  182. {
  183.     register Long __huge *ptr;
  184.     register Long __huge *end;
  185.     register Long fill;
  186.  
  187.     if( !FBClear )
  188.     {   FBClear = True;
  189.     fill = Lut[BackCol];
  190. #ifdef EIGHTBIT
  191.     fill |= fill<<8;
  192.     fill |= fill<<16;
  193. #endif
  194.     ptr = (Long __huge*)FBuffer;
  195.     end = (Long __huge*)(FBuffer+(Long)XRange*YRange);
  196.     do { *ptr++=fill; *ptr++=fill;
  197.          *ptr++=fill; *ptr++=fill;
  198.     } while( ptr<end );
  199.     }
  200.  
  201.     if( !DBClear )
  202.     {   DBClear = True;
  203.     ptr = (Long __huge*)DBuffer;
  204.     end = (Long __huge*)(DBuffer+(Long)XRange*YRange);
  205.     do { *ptr++=0; *ptr++=0;
  206.          *ptr++=0; *ptr++=0;
  207.     } while( ptr<end );
  208.     }
  209. }
  210. #endif
  211.  
  212. void ReAllocBuffers()
  213. {
  214.     register Atom __far * __far *iptr;
  215.     register int index,len;
  216.     register Long temp;
  217.  
  218.     temp = (Long)XRange*YRange*sizeof(short)+32;
  219. #ifdef IBMPC
  220.     if( DBufHandle ) GlobalFree(DBufHandle);
  221.     DBufHandle = GlobalAlloc(GMEM_MOVEABLE,temp);
  222.     if( !DBufHandle ) FatalRenderError("depth buffer");
  223. #else
  224.     if( DBuffer ) _ffree( DBuffer );
  225.     DBuffer = (short*)_fmalloc( temp );
  226.     if( !DBuffer ) FatalRenderError("depth buffer");
  227. #endif
  228.     DBClear=False;
  229.  
  230.     if( YBucket && (BuckY<YRange) )
  231.     {   _ffree(YBucket); 
  232.     YBucket=(void __far*)0; 
  233.     }
  234.  
  235.     if( !YBucket )
  236.     {   len = YRange*sizeof(Atom __far*);
  237.     YBucket = (Atom __far* __far*)_fmalloc( len );
  238.     if( !YBucket ) FatalRenderError("Y buckets");
  239.     BuckY = YRange;
  240.     }
  241.  
  242.     if( IBuffer && (ItemX<XRange) )
  243.     {   _ffree(IBuffer); 
  244.     IBuffer=(void __far*)0; 
  245.     }
  246.  
  247.     if( !IBuffer )
  248.     {   len = (XRange+4)*sizeof(Atom __far*);
  249.     IBuffer = (Atom __far* __far*)_fmalloc(len);
  250.     if( !IBuffer ) FatalRenderError("item buffer");
  251.     len = XRange>>2;  iptr = IBuffer;
  252.     for( index=0; index<=len; index++ )
  253.     {   *iptr++ = (void __far*)0;  *iptr++ = (void __far*)0;
  254.         *iptr++ = (void __far*)0;  *iptr++ = (void __far*)0;
  255.     }
  256.     ItemX = XRange;
  257.     }
  258. }
  259.  
  260.  
  261. void ReSizeScreen()
  262. {
  263.     register Real orig;
  264.  
  265.     if( Range != ZoomRange )
  266.     {   orig = MaxZoom;
  267.     MaxZoom = 0.236*(WorldSize+1000)/Range;
  268.     ZoomRange = Range;  MaxZoom -= 1.0;
  269.  
  270.     /* Handle Change in MaxZoom */
  271.     if( DialValue[3]>0.0 )
  272.     {   DialValue[3] *= orig/MaxZoom;
  273.         if( DialValue[3]>1.0 )
  274.         DialValue[3] = 1.0;
  275.     }
  276.     }
  277.  
  278. #ifdef IBMPC
  279.     if( !FBufHandle || (FBufX!=XRange) || (FBufY!=YRange) )
  280. #else /* UNIX */
  281.     if( !FBuffer || (FBufX!=XRange) || (FBufY!=YRange) )
  282. #endif
  283.     {   if( !CreateImage() )
  284.         FatalRenderError("frame buffer");
  285.  
  286.     BucketFlag = False;
  287.     FBufX=XRange;  FBufY=YRange;  FBClear = False;
  288.     ReAllocBuffers();
  289.     ClearBuffers();
  290.     }
  291. }
  292.  
  293.  
  294.  
  295. static void PrepareYBucket()
  296. {
  297.     register Atom __far * __far *temp;
  298.     register Chain __far *chain;
  299.     register Group __far *group;
  300.     register Atom __far *aptr;
  301.     register int scan;
  302.     register int rad;
  303.  
  304.     temp = YBucket;
  305.     for( scan=0; scan<BuckY; scan++ )
  306.     *temp++ = (void __far*)0;
  307.  
  308.     if( UseClipping )
  309.     {   ForEachAtom
  310.         if( aptr->flag&SphereFlag )
  311.         {   rad = aptr->irad;
  312.         if( (aptr->x-rad>=XRange) || 
  313.             (aptr->x+rad<0) || (aptr->y+rad<0) )
  314.             continue;
  315.         if( (scan=aptr->y-rad) > BuckY ) continue;
  316.  
  317.         if( scan>0 )
  318.         {   aptr->bucket = YBucket[scan];
  319.             YBucket[scan] = aptr;
  320.         } else
  321.         {   aptr->bucket = *YBucket;
  322.             *YBucket = aptr;
  323.         }
  324.         }
  325.     } else
  326.     ForEachAtom
  327.         if( aptr->flag&SphereFlag )
  328.         {   scan = aptr->y-aptr->irad;
  329.         aptr->bucket = YBucket[scan];
  330.         YBucket[scan] = aptr;
  331.         }
  332.     BucketFlag = True;
  333. }
  334.  
  335. #ifdef FUNCPROTO
  336. /* Function Prototypes */
  337. static void SqrInterval( Interval __far* );
  338. static void VoxelInsert( Atom __far*, int );
  339. static int AtomInter( Atom __far* );
  340. #endif
  341.  
  342.  
  343. static void SqrInterval( ival )
  344.     Interval __far *ival;
  345. {   register Real l,h;
  346.  
  347.     l = ival->l;
  348.     h = ival->h;
  349.  
  350.     if( l>=0.0 )
  351.     {   ival->l = l*l;
  352.     ival->h = h*h;
  353.     } else if( h<0.0 )
  354.     {   ival->l = h*h;
  355.     ival->h = l*l;
  356.     } else
  357.     {   ival->h = (-l>h)? l*l : h*h;
  358.     ival->l = 0.0;
  359.     }
  360. }
  361.  
  362. static void VoxelInsert( ptr, ref )
  363.     Atom __far *ptr;
  364.     int ref;
  365. {
  366.     register Item __far *datum;
  367.     register int i;
  368.  
  369.     if( !FreeItem )
  370.     {   datum = (Item __far*)_fmalloc( PoolSize*sizeof(Item) );
  371.     if( !datum ) FatalRenderError("voxel item");
  372.     for( i=1; i<PoolSize; i++ )
  373.     {   datum->list = FreeItem;
  374.         FreeItem = datum++;
  375.     }
  376.     } else
  377.     {   datum = FreeItem;
  378.     FreeItem = datum->list;
  379.     }
  380.     datum->data = ptr;
  381.     InVoxCount++;
  382.  
  383.     if( !HashTable[ref] ) VoxelCount++;
  384.     datum->list = (Item __far*)HashTable[ref];
  385.     HashTable[ref] = (void __far*)datum;
  386. }
  387.  
  388.  
  389. void ResetVoxelData()
  390. {
  391.     register Item __far *datum;
  392.     register int i;
  393.  
  394.     if( VoxelsDone )
  395.     {   for( i=0; i<VOXSIZE; i++ )
  396.         if( datum = (Item __far*)HashTable[i] )
  397.         {   while( datum->list ) datum = datum->list;
  398.         datum->list = FreeItem;
  399.         FreeItem = (Item __far*)HashTable[i];
  400.         HashTable[i] = (void __far*)0;
  401.         }
  402.     VoxelsDone = False;
  403.     } else for( i=0; i<VOXSIZE; i++ )
  404.     HashTable[i] = (void __far*)0;
  405.     VoxelsClean = True;
  406. }
  407.  
  408.  
  409. static void CreateVoxelData( flag )
  410.     int flag;
  411. {
  412.     static Interval ix, iy, iz;
  413.     register int lvx, lvy, lvz;
  414.     register int hvx, hvy, hvz;
  415.     register Long mx, my, mz;
  416.     register int px, py, pz;
  417.     register int i, rad;
  418.     register Real radius2;
  419.  
  420.     register Chain __far *chain;
  421.     register Group __far *group;
  422.     register Atom __far *aptr;
  423.  
  424.  
  425.     ResetVoxelData();
  426.     ProbeCount = InVoxCount = VoxelCount = 0;
  427.     VoxRatio = (Real)SideLen/VOXORDER;
  428.     IVoxRatio = 1.0/VoxRatio;
  429.     VoxelsDone = True;
  430.  
  431.     ForEachAtom
  432.     if( aptr->flag & flag )
  433.     {   mx = aptr->xorg+Offset;
  434.     my = aptr->yorg+Offset;
  435.     mz = aptr->zorg+Offset;
  436.     if( flag != SphereFlag )
  437.     {   if( SolventDots || !ProbeRadius )
  438.         {   rad = ElemVDWRadius(GetElemNumber(aptr));
  439.         } else rad = ProbeRadius;
  440.     } else rad = aptr->radius;  
  441.     radius2 = (Long)rad*rad;
  442.  
  443.     lvx = (int)((mx-rad)*IVoxRatio);  hvx = (int)((mx+rad)*IVoxRatio);
  444.     lvy = (int)((my-rad)*IVoxRatio);  hvy = (int)((my+rad)*IVoxRatio);
  445.     lvz = (int)((mz-rad)*IVoxRatio);  hvz = (int)((mz+rad)*IVoxRatio);
  446.  
  447.  
  448.     for( px=lvx; px<=hvx; px++ )
  449.     {   ix.l=px*VoxRatio-mx;
  450.         ix.h=ix.l+VoxRatio;  
  451.         SqrInterval(&ix);
  452.         i = VOXORDER2*px + VOXORDER*lvy;
  453.        
  454.         for( py=lvy; py<=hvy; py++ )
  455.         {   iy.l=py*VoxRatio-my;
  456.         iy.h=iy.l+VoxRatio;
  457.         SqrInterval(&iy);
  458.         
  459.         for( pz=lvz; pz<=hvz; pz++ )
  460.         {   iz.l=pz*VoxRatio-mz; 
  461.             iz.h=iz.l+VoxRatio;
  462.             SqrInterval(&iz);
  463.  
  464.             if( ((ix.h+iy.h+iz.h)>radius2) && 
  465.             ((ix.l+iy.l+iz.l)<radius2) )
  466.             VoxelInsert( aptr, i+pz );
  467.         } /*pz*/
  468.         i += VOXORDER;
  469.         } /*py*/
  470.     } /*px*/
  471.     }
  472. }
  473.  
  474.  
  475. void ShadowTransform()
  476. {
  477.     ShadowI = OneOverRootSix*(RotX[0]-RotY[0]+RotZ[0]+RotZ[0]);
  478.     ShadowK = OneOverRootSix*(RotX[2]-RotY[2]+RotZ[2]+RotZ[2]);
  479. #ifdef INVERT
  480.     ShadowJ = -OneOverRootSix*(RotX[1]-RotY[1]+RotZ[1]+RotZ[1]);
  481. #else
  482.     ShadowJ =  OneOverRootSix*(RotX[1]-RotY[1]+RotZ[1]+RotZ[1]);
  483. #endif
  484.  
  485.     if( ShadowI>ApproxZero )
  486.     {   deltax =  (int)(FUDGEFACTOR/ShadowI); xhash =  VOXORDER2; xflag =  1;
  487.     } else if( ShadowI<-ApproxZero )
  488.     {   deltax = -(int)(FUDGEFACTOR/ShadowI); xhash = -VOXORDER2; xflag = -1;
  489.     } else xflag = 0;
  490.  
  491.     if( ShadowJ>ApproxZero )
  492.     {   deltay =  (int)(FUDGEFACTOR/ShadowJ); yhash =  VOXORDER; yflag =  1;
  493.     } else if( ShadowJ<-ApproxZero )
  494.     {   deltay = -(int)(FUDGEFACTOR/ShadowJ); yhash = -VOXORDER; yflag = -1;
  495.     } else yflag = 0;
  496.  
  497.     if( ShadowK>ApproxZero )
  498.     {   deltaz =  (int)(FUDGEFACTOR/ShadowK); zhash = zflag =  1;
  499.     } else if( ShadowK<-ApproxZero )
  500.     {   deltaz = -(int)(FUDGEFACTOR/ShadowK); zhash = zflag = -1;
  501.     } else zflag = 0;
  502. }
  503.  
  504.  
  505. static int AtomInter( ptr )
  506.     Atom __far *ptr;
  507. {
  508.     register Long modv,radius2;
  509.     register int vx, vy, vz;
  510.     register Real tca;
  511.  
  512.     if( ptr->mbox == RayCount )
  513.     return( False );
  514.     ptr->mbox = RayCount;
  515.  
  516.     vx = (int)ptr->xorg-ShadowX;
  517.     vy = (int)ptr->yorg-ShadowY;
  518.     vz = (int)ptr->zorg-ShadowZ;
  519.  
  520.     tca = vx*ShadowI + vy*ShadowJ + vz*ShadowK;
  521.     if( tca<0.0 ) return( False );
  522.     
  523.     radius2 = ptr->radius+10;  radius2 = radius2*radius2;
  524.     modv = (Long)vx*vx + (Long)vy*vy + (Long)vz*vz - radius2;
  525.     return( modv<tca*tca );
  526. }
  527.  
  528.  
  529. static int ShadowRay()
  530. {
  531.     register Item __far * __far *ident;
  532.     register Item __far *ptr;
  533.     register Real ex, ey, ez;
  534.     register Long dx, dy, dz;
  535.     register int ref;
  536.  
  537.    
  538.     RayCount++;
  539.     if( SBuffer )
  540.     {   if( (SBuffer!=Exclude) && AtomInter(SBuffer) )
  541.         return( True );
  542.     SBuffer = (void __far*)0;
  543.     }
  544.  
  545.     ex = IVoxRatio*(ShadowX+Offset);  xcord = (int)ex;
  546.     ey = IVoxRatio*(ShadowY+Offset);  ycord = (int)ey;
  547.     ez = IVoxRatio*(ShadowZ+Offset);  zcord = (int)ez;
  548.  
  549.     ref = VOXORDER2*xcord+VOXORDER*ycord+zcord;
  550.     ident = (Item __far* __far*)(HashTable+ref);
  551.  
  552.     if( xflag==1 ) 
  553.     {   dx = (Long)(((xcord+1)-ex)*deltax);
  554.     } else if( xflag == -1 )
  555.     {   dx = (Long)((ex-xcord)*deltax); 
  556.     } else dx = INFINITY;
  557.  
  558.     if( yflag==1 ) 
  559.     {   dy = (Long)(((ycord+1)-ey)*deltay);
  560.     } else if( yflag == -1 )
  561.     {   dy = (Long)((ey-ycord)*deltay); 
  562.     } else dy = INFINITY;
  563.  
  564.     if( zflag==1 ) 
  565.     {   dz = (Long)(((zcord+1)-ez)*deltaz);
  566.     } else if( zflag == -1 )
  567.     {   dz = (Long)((ez-zcord)*deltaz); 
  568.     } else dz = INFINITY;
  569.  
  570.     
  571.     while( True )
  572.     {   for( ptr = *ident; ptr; ptr = ptr->list )
  573.         if( (ptr->data!=Exclude) && AtomInter(ptr->data) )
  574.         {   SBuffer = ptr->data;
  575.         return( True );
  576.         }
  577.  
  578.     if( (dx<=dy) && (dx<=dz) )
  579.     {   xcord += xflag;
  580.         if( (xcord<0) || (xcord>=VOXORDER) ) return( False );
  581.         ident += xhash; dx += deltax;
  582.     } else if( dy<=dz  ) /*(dy<=dx)*/
  583.     {   ycord += yflag;
  584.         if( (ycord<0) || (ycord>=VOXORDER) ) return( False );
  585.         ident += yhash; dy += deltay;
  586.     } else /* (dz<=dx) && (dz<=dy) */
  587.     {   zcord += zflag;
  588.         if( (zcord<0) || (zcord>=VOXORDER) ) return( False );
  589.         ident += zhash; dz += deltaz;
  590.     }
  591.     }
  592. }
  593.  
  594.  
  595.  
  596. #define UpdateScanAcross \
  597.     if( depth>*dptr )   \
  598.     {   *dptr = depth;  \
  599.         iptr[dx] = ptr; \
  600.     } dptr++; dx++;
  601.  
  602.  
  603. /* ScanLine for Shadows! */
  604. static void ScanLine()
  605. {
  606.     static Atom __far *list;
  607.     register Atom __far *ptr;
  608.     register Atom __far * __far *iptr;
  609.     register Atom __far * __far *prev;
  610.     register short __huge *dbase;
  611.     register short __huge *dptr;
  612.     register Pixel __huge *fptr;
  613.     register Byte __far *tptr;
  614.  
  615.     register int pos,depth,inten;
  616.     register int lastx,wide,scan;
  617.     register int dx,dy,dz;
  618.  
  619.     fptr = FBuffer;
  620.     dbase = DBuffer;
  621.     list = (void __far*)0;  
  622.  
  623.     wide = XRange>>2;  iptr = IBuffer;
  624.     for( pos=0; pos<=wide; pos++ )
  625.     {   *iptr++ = (void __far*)0;  *iptr++ = (void __far*)0;
  626.     *iptr++ = (void __far*)0;  *iptr++ = (void __far*)0;
  627.     }
  628.  
  629.  
  630.     for( scan=0; scan<YRange; scan++ )
  631.     {   for( ptr = YBucket[scan]; ptr; ptr = ptr->bucket )
  632.     {    ptr->next = list; list = ptr; }
  633.  
  634.     prev = &list;
  635.     for( ptr=list; ptr; ptr=ptr->next )
  636.     {   dy = scan - ptr->y;
  637.         wide = LookUp[ptr->irad][AbsFun(dy)];
  638.         lastx = (XRange-1)-ptr->x;
  639.         if( wide<lastx ) lastx=wide;
  640.         dx = - MinFun(wide,ptr->x);
  641.  
  642.         iptr = IBuffer+ptr->x;
  643.         tptr = LookUp[wide];
  644.  
  645.         dptr = dbase+ptr->x+dx;
  646.         while( dx<=lastx )
  647.         {   depth = tptr[AbsFun(dx)]+ptr->z;
  648.         UpdateScanAcross;
  649.         }
  650.  
  651.         /* Remove completed atoms */
  652.         if( dy == ptr->irad )
  653.         {   *prev = ptr->next;
  654.         } else prev = &ptr->next;
  655.     } /*ptr*/
  656.  
  657.  
  658.     /* Process visible scanline */
  659.     prev = (Atom __far* __far*)IBuffer;
  660.     SBuffer = (void __far*)0;
  661.     dptr = dbase; 
  662.  
  663.     for( pos=0; pos<XRange; pos++ )
  664.     {   if( ptr = *prev )
  665.         {   dz = *dptr-ptr->z;
  666. #ifdef INVERT
  667.         inten = (dz<<1)+(pos-ptr->x)+(scan-ptr->y);
  668. #else
  669.         inten = (dz<<1)+(pos-ptr->x)-(scan-ptr->y);
  670. #endif
  671.         if( inten>0 )
  672.         {   inten = (int)( (inten*ColConst[ptr->irad])>>ColBits);
  673.             dz = *dptr-ZOffset;
  674.             dx = pos-XOffset;
  675.             dy =   scan-YOffset;
  676.  
  677.             ShadowX = (int)(dx*InvX[0]+dy*InvX[1]+dz*InvX[2]);
  678.             ShadowY = (int)(dx*InvY[0]+dy*InvY[1]+dz*InvY[2]);
  679.             ShadowZ = (int)(dx*InvZ[0]+dy*InvZ[1]+dz*InvZ[2]);
  680.  
  681.             Exclude = ptr;
  682.             if( ShadowRay() )
  683.             {   *fptr = Lut[ptr->col+(inten>>2)];
  684.             } else *fptr = Lut[ptr->col+inten];
  685.         } else *fptr = Lut[ptr->col];
  686.         *prev = (void __far*)0;
  687.         }
  688.         dptr++; fptr++; prev++;
  689.     }
  690.     dbase = dptr;
  691.     } /*scan*/
  692. }
  693.  
  694.  
  695. #ifdef FUNCPROTO
  696. /* Function Prototype */
  697. static void DisplayHBonds( HBond __far *, int );
  698. static void DisplayRibbon( Chain __far * );
  699. #endif
  700.  
  701.  
  702. static void DisplaySpaceFill()
  703. {
  704.     register Chain __far *chain;
  705.     register Group __far *group;
  706.     register Atom __far *aptr;
  707.  
  708.     if( UseShadow )
  709.     {   if( !BucketFlag )
  710.         PrepareYBucket();
  711.     ScanLine();
  712.     } else if( UseClipping )
  713.     {   ForEachAtom
  714.         if( aptr->flag&SphereFlag )
  715.         ClipSphere(aptr->x,aptr->y,aptr->z,aptr->irad,aptr->col);
  716.     } else 
  717.     ForEachAtom
  718.         if( aptr->flag&SphereFlag )
  719.         DrawSphere(aptr->x,aptr->y,aptr->z,aptr->irad,aptr->col);
  720. }
  721.  
  722.  
  723. static void DisplayWireFrame()
  724. {
  725.     register Bond __far *bptr;
  726.     register Atom __far *s;
  727.     register Atom __far *d;
  728.     register int sc,dc;
  729.  
  730.     if( UseClipping )
  731.     {   ForEachBond
  732.        if( bptr->flag&WireFlag )
  733.        {   s = bptr->srcatom; d = bptr->dstatom;
  734.            if( !bptr->col ) 
  735.            {   sc = s->col;  dc = d->col;
  736.            } else sc = dc = bptr->col;
  737.            ClipTwinVector(s->x,s->y,s->z,d->x,d->y,d->z,sc,dc);
  738.        } else if( bptr->flag&CylinderFlag )
  739.        {   s = bptr->srcatom; d = bptr->dstatom;
  740.            if( !bptr->col ) 
  741.            {   sc = s->col;  dc = d->col;
  742.            } else sc = dc = bptr->col;
  743.  
  744.            if( bptr->irad>0 )
  745.            {  ClipCylinder(s->x,s->y,s->z,sc,d->x,d->y,d->z,dc,bptr->irad);
  746.            } else ClipTwinLine(s->x,s->y,s->z,d->x,d->y,d->z,
  747.                    sc+ColourMask,dc+ColourMask);
  748.        }
  749.     } else
  750.     ForEachBond
  751.        if( bptr->flag&WireFlag )
  752.        {   s = bptr->srcatom; d = bptr->dstatom;
  753.            if( !bptr->col ) 
  754.            {   sc = s->col;  dc = d->col;
  755.            } else sc = dc = bptr->col;
  756.            DrawTwinVector(s->x,s->y,s->z,d->x,d->y,d->z,sc,dc);
  757.        } else if( bptr->flag&CylinderFlag )
  758.        {   s = bptr->srcatom; d = bptr->dstatom;
  759.            if( !bptr->col ) 
  760.            {   sc = s->col;  dc = d->col;
  761.            } else sc = dc = bptr->col;
  762.  
  763.            if( bptr->irad>0 )
  764.            {  DrawCylinder(s->x,s->y,s->z,sc,d->x,d->y,d->z,dc,bptr->irad);
  765.            } else DrawTwinLine(s->x,s->y,s->z,d->x,d->y,d->z,
  766.                    sc+ColourMask,dc+ColourMask);
  767.        }
  768. }
  769.  
  770.  
  771. static void DisplayBackBone()
  772. {
  773.     register Chain __far *chain;
  774.     register Bond __far *bptr;
  775.     register Atom __far *s;
  776.     register Atom __far *d;
  777.     register int sc,dc;
  778.  
  779.     ForEachBack
  780.        if( bptr->flag&DrawBondFlag )
  781.        {   s = bptr->srcatom; d = bptr->dstatom;
  782.        if( !bptr->col ) 
  783.        {   sc = s->col;  dc = d->col;
  784.        } else sc = dc = bptr->col;
  785.  
  786.        if( bptr->flag&CylinderFlag )
  787.        {   if( bptr->irad>0 )
  788.            { ClipCylinder(s->x,s->y,s->z,sc,d->x,d->y,d->z,dc,bptr->irad);
  789.            } else ClipTwinLine(s->x,s->y,s->z,d->x,d->y,d->z,
  790.                    sc+ColourMask,dc+ColourMask);
  791.        } else ClipTwinVector(s->x,s->y,s->z,d->x,d->y,d->z,sc,dc);
  792.        }
  793. }
  794.  
  795.  
  796. static void DisplayHBonds( list, mode )
  797.     HBond __far *list; 
  798.     int mode;
  799. {
  800.     register HBond __far *ptr;
  801.     register Atom __far *s;
  802.     register Atom __far *d;
  803.     register int sc,dc;
  804.  
  805.     for( ptr=list; ptr; ptr=ptr->hnext )
  806.     if( ptr->flag & DrawBondFlag )
  807.     {   if( mode )
  808.         {   s = ptr->srcCA; d = ptr->dstCA;
  809.         if( !s || !d ) continue;
  810.         } else
  811.         {   d = ptr->src;
  812.         s = ptr->dst;
  813.         }
  814.  
  815.         if( !ptr->col )
  816.         {   sc = s->col;  dc = d->col;
  817.         } else sc = dc = ptr->col;
  818.         if( ptr->flag & CylinderFlag )
  819.         {   if( ptr->irad>0 )
  820.         {   ClipCylinder(s->x,s->y,s->z,sc,
  821.                  d->x,d->y,d->z,dc,ptr->irad);
  822.         } else ClipTwinLine(s->x,s->y,s->z,d->x,d->y,d->z,
  823.                     sc+ColourMask,dc+ColourMask);
  824.         } else ClipDashVector(s->x,s->y,s->z,d->x,d->y,d->z,sc,dc);
  825.     }
  826. }
  827.  
  828.  
  829.  
  830. static void CalculateInten( ptr )
  831.     Knot *ptr;
  832. {
  833.     register Real inten;
  834.     register int size;
  835.  
  836.     size = isqrt( (Long)ptr->cx*ptr->cx + 
  837.           (Long)ptr->cy*ptr->cy + 
  838.           (Long)ptr->cz*ptr->cz );
  839.  
  840.     if( size )
  841.     {   
  842. #ifdef INVERT
  843.     inten = ptr->cx + ptr->cy + ptr->cz + ptr->cz;
  844. #else
  845.     inten = ptr->cx - ptr->cy + ptr->cz + ptr->cz;
  846. #endif
  847.     inten /= size*RootSix;
  848.     if( ptr->cz < 0 ) inten = -inten;
  849.  
  850.     ptr->inten = (int)(ColourMask*inten);
  851.     if( ptr->inten<0 ) ptr->inten = 0;
  852.     } else ptr->inten = ColourMask;
  853. }
  854.  
  855.  
  856. static void DisplayRibbon( chain )
  857.     Chain  __far *chain;
  858. {
  859.     register Group __far *group;
  860.     register Atom __far *captr;
  861.     register Atom __far *o1ptr;
  862.     register Atom __far *o2ptr;
  863.     register Atom __far *next;
  864.  
  865.     register int prev,wide;
  866.     register int col1,col2;
  867.     register int bx,by,bz;
  868.     register int dx,dy,dz;
  869.     register int size;
  870.  
  871.     static Knot mid1, mid2, mid3;
  872.     static Knot knot1, knot2;
  873.  
  874.     prev = False;  
  875.     group = chain->glist;
  876.     if( IsAmino(group->refno) )
  877.     {   captr = FindGroupAtom(group,1);
  878.     } else captr = FindGroupAtom(group,7);
  879.  
  880.     while( group->gnext )
  881.     {   if( IsAmino(group->gnext->refno) )
  882.     {   next = FindGroupAtom(group->gnext,1);
  883.         o1ptr = FindGroupAtom(group,3);
  884.     } else /* Nucleic Acid */
  885.     {   next = FindGroupAtom(group->gnext,7);
  886.         o1ptr = FindGroupAtom(group->gnext,10);
  887.     }
  888.  
  889.     /* When not to have a control point! */
  890.     if( !next || !captr || !o1ptr || (next->flag&BreakFlag) ||
  891.         !((group->flag|group->gnext->flag)&(RibbonFlag|StrandFlag)) )
  892.     {   group = group->gnext;
  893.         captr = next;
  894.         prev = False;
  895.         continue;
  896.     }
  897.  
  898.     knot2.tx = next->x - captr->x;
  899.     knot2.ty = next->y - captr->y;
  900.     knot2.tz = next->z - captr->z;
  901.  
  902.     if( IsAmino(group->refno) )
  903.     {   bx = o1ptr->x - captr->x;
  904.         by = o1ptr->y - captr->y;
  905.         bz = o1ptr->z - captr->z;
  906.  
  907.     } else if( !FindGroupAtom(group,17) && 
  908.            (o2ptr=FindGroupAtom(group,8)) )
  909.     {   /* Deoxyribonucleic Acid */
  910.         o2ptr = FindGroupAtom(group,8);
  911.         bx = (o1ptr->x + o2ptr->x)/2 - captr->x;
  912.         by = (o1ptr->y + o2ptr->y)/2 - captr->y;
  913.         bz = (o1ptr->z + o2ptr->z)/2 - captr->z;
  914.  
  915.     } else /* Ribonucleic Acid */
  916.     {   bx = o1ptr->x - captr->x;
  917.         by = o1ptr->y - captr->y;
  918.         bz = o1ptr->z - captr->z;
  919.     }
  920.  
  921.     /* c := a x b */
  922.     knot2.cx = knot2.ty*bz - knot2.tz*by;
  923.     knot2.cy = knot2.tz*bx - knot2.tx*bz;
  924.     knot2.cz = knot2.tx*by - knot2.ty*bx;
  925.  
  926.     knot2.px = (captr->x + next->x)/2;
  927.     knot2.py = (captr->y + next->y)/2;
  928.     knot2.pz = (captr->z + next->z)/2;
  929.  
  930.     if( (group->struc&group->gnext->struc) & HelixFlag )
  931.     {   size = isqrt((Long)knot2.cx*knot2.cx + 
  932.              (Long)knot2.cy*knot2.cy + 
  933.              (Long)knot2.cz*knot2.cz);
  934.  
  935.         if( size )
  936.         {   wide = (int)(375*Scale);
  937.  
  938. #ifdef INVERT
  939.         knot2.px += (int)(((Long)wide*knot2.cx)/size);
  940.         knot2.py += (int)(((Long)wide*knot2.cy)/size);
  941.         knot2.pz += (int)(((Long)wide*knot2.cz)/size);
  942. #else
  943.         knot2.px -= (int)(((Long)wide*knot2.cx)/size);
  944.         knot2.py -= (int)(((Long)wide*knot2.cy)/size);
  945.         knot2.pz -= (int)(((Long)wide*knot2.cz)/size);
  946. #endif
  947.         }
  948.     }
  949.  
  950.     /* d := c x a */
  951.     dx = (int)(((Long)knot2.cy*knot2.tz - 
  952.             (Long)knot2.cz*knot2.ty)/96);
  953.     dy = (int)(((Long)knot2.cz*knot2.tx - 
  954.             (Long)knot2.cx*knot2.tz)/96);
  955.     dz = (int)(((Long)knot2.cx*knot2.ty - 
  956.             (Long)knot2.cy*knot2.tx)/96);
  957.  
  958.     /* Average Ribbon Width */
  959.     if( group->flag & (RibbonFlag|StrandFlag) )
  960.     {   if( group->gnext->flag & (RibbonFlag|StrandFlag) )
  961.         {   wide = (group->width+group->gnext->width)>>1;
  962.         } else wide = group->width;
  963.     } else wide = group->gnext->width;
  964.  
  965.     wide = (int)(wide*Scale);
  966.  
  967.     size = isqrt((Long)dx*dx + (Long)dy*dy + (Long)dz*dz);
  968.  
  969.     if( size )
  970.     {   dx = (int)(((Long)wide*dx)/size);
  971.         dy = (int)(((Long)wide*dy)/size);
  972.         dz = (int)(((Long)wide*dz)/size);
  973.  
  974.         /* Handle Carbonyl Oxygen Flip */
  975.         if( prev && ((knot1.wx*dx + knot1.wy*dy + knot1.wz*dz) < 0) )
  976.         {   knot2.wx = -dx;
  977.         knot2.wy = -dy;
  978.         knot2.wz = -dz;
  979.         } else
  980.         {   knot2.wx = dx;
  981.         knot2.wy = dy;
  982.         knot2.wz = dz;
  983.         }
  984.     } else
  985.     {   knot2.wx = 0;
  986.         knot2.wy = 0;
  987.         knot2.wz = 0;
  988.     }
  989.  
  990.  
  991.     if( (group->flag|group->gnext->flag)&RibbonFlag )
  992.         CalculateInten( &knot2 );
  993.  
  994.     if( !(col1 = group->col1) )
  995.         col1 = captr->col;
  996.     if( !(col2 = group->col2) )
  997.         col2 = captr->col;
  998.         
  999.  
  1000.     if( prev )
  1001.     {   /* Approximate spline segment with straight line! */
  1002.         /* StrandRibbon( &knot1, &knot2, col1, col2 );   */
  1003.  
  1004.         /* Calculate Hermite Spline Points */
  1005.         mid1.px = (int)(((Long)54*knot1.px + (Long)9*knot1.tx +
  1006.                  (Long)10*knot2.px - (Long)3*knot2.tx)>>6);
  1007.         mid1.py = (int)(((Long)54*knot1.py + (Long)9*knot1.ty +
  1008.                  (Long)10*knot2.py - (Long)3*knot2.ty)>>6);
  1009.         mid1.pz = (int)(((Long)54*knot1.pz + (Long)9*knot1.tz +
  1010.                  (Long)10*knot2.pz - (Long)3*knot2.tz)>>6);
  1011.  
  1012.         mid2.px = (int)(((Long)4*knot1.px + knot1.tx + 
  1013.                  (Long)4*knot2.px - knot2.tx)>>3);
  1014.         mid2.py = (int)(((Long)4*knot1.py + knot1.ty + 
  1015.                  (Long)4*knot2.py - knot2.ty)>>3);
  1016.         mid2.pz = (int)(((Long)4*knot1.pz + knot1.tz + 
  1017.                  (Long)4*knot2.pz - knot2.tz)>>3);
  1018.  
  1019.         mid3.px = (int)(((Long)10*knot1.px + (Long)3*knot1.tx +
  1020.                  (Long)54*knot2.px - (Long)9*knot2.tx)>>6);
  1021.         mid3.py = (int)(((Long)10*knot1.py + (Long)3*knot1.ty +
  1022.                  (Long)54*knot2.py - (Long)9*knot2.ty)>>6);
  1023.         mid3.pz = (int)(((Long)10*knot1.pz + (Long)3*knot1.tz +
  1024.                  (Long)54*knot2.pz - (Long)9*knot2.tz)>>6);
  1025.  
  1026.         /* Calculate Hermite Spline Widths */
  1027.         mid1.wx = (27*knot1.wx + 5*knot2.wx)>>5;
  1028.         mid1.wy = (27*knot1.wy + 5*knot2.wy)>>5;
  1029.         mid1.wz = (27*knot1.wz + 5*knot2.wz)>>5;
  1030.  
  1031.         mid2.wx = (knot1.wx + knot2.wx)>>1;
  1032.         mid2.wy = (knot1.wy + knot2.wy)>>1;
  1033.         mid2.wz = (knot1.wz + knot2.wz)>>1;
  1034.  
  1035.         mid3.wx = (5*knot1.wx + 27*knot2.wx)>>5;
  1036.         mid3.wy = (5*knot1.wy + 27*knot2.wy)>>5;
  1037.         mid3.wz = (5*knot1.wz + 27*knot2.wz)>>5;
  1038.  
  1039.         /* Draw the Spline Segments */
  1040.         if( group->flag & RibbonFlag )
  1041.         {   mid1.cx = (27*knot1.cx + 5*knot2.cx)>>5;
  1042.         mid1.cy = (27*knot1.cy + 5*knot2.cy)>>5;
  1043.         mid1.cz = (27*knot1.cz + 5*knot2.cz)>>5;
  1044.         CalculateInten(&mid1);
  1045.  
  1046.         mid2.cx = (knot1.cx + knot2.cx)>>1;
  1047.         mid2.cy = (knot1.cy + knot2.cy)>>1;
  1048.         mid2.cz = (knot1.cz + knot2.cz)>>1;
  1049.         CalculateInten(&mid2);
  1050.  
  1051.         mid3.cx = (5*knot1.cx + 27*knot2.cx)>>5;
  1052.         mid3.cy = (5*knot1.cy + 27*knot2.cy)>>5;
  1053.         mid3.cz = (5*knot1.cz + 27*knot2.cz)>>5;
  1054.         CalculateInten(&mid3);
  1055.  
  1056.         SolidRibbon( &knot1, &mid1,  col1 );
  1057.         SolidRibbon( &mid1,  &mid2,  col1 );
  1058.         SolidRibbon( &mid2,  &mid3,  col1 );
  1059.         SolidRibbon( &mid3,  &knot2, col1 );
  1060.  
  1061.         } else if( group->flag & StrandFlag )
  1062.         {   StrandRibbon( &knot1, &mid1,  col1, col2 );
  1063.         StrandRibbon( &mid1,  &mid2,  col1, col2 );
  1064.         StrandRibbon( &mid2,  &mid3,  col1, col2 );
  1065.         StrandRibbon( &mid3,  &knot2, col1, col2 );
  1066.         }
  1067.     } else prev = True;
  1068.  
  1069.     group = group->gnext;
  1070.     captr = next;
  1071.  
  1072.     knot1 = knot2;
  1073.     }
  1074. }
  1075.  
  1076.  
  1077.  
  1078. static void ResetLabels()
  1079. {
  1080.     register Label *ptr;
  1081.  
  1082.     while( LabelList )
  1083.     {   ptr = LabelList;
  1084.     LabelList = ptr->next;
  1085.     ptr->next = FreeLabel;
  1086.     free(ptr->label);
  1087.     FreeLabel = ptr;
  1088.     }
  1089. }
  1090.  
  1091.  
  1092. int DeleteLabels()
  1093. {
  1094.     register Chain __far *chain;
  1095.     register Group __far *group;
  1096.     register Atom __far *aptr;
  1097.     register Label *label;
  1098.     register Label **ptr;
  1099.     register int result;
  1100.  
  1101.     if( !Database )
  1102.     return( True );
  1103.  
  1104.     result = True;
  1105.     DrawLabels = False;
  1106.  
  1107.     ForEachAtom
  1108.     if( aptr->flag & SelectFlag )
  1109.     {   result = False;
  1110.         if( aptr->label )
  1111.         {   label = (Label*)aptr->label;
  1112.         aptr->label = (void*)0;
  1113.         label->refcount--;
  1114.         result = False;
  1115.  
  1116.         if( !label->refcount )
  1117.         {   ptr = &LabelList;
  1118.             while( *ptr != label )
  1119.                ptr = &(*ptr)->next;
  1120.  
  1121.             *ptr = label->next;
  1122.             label->next = FreeLabel;
  1123.             free(label->label);
  1124.             FreeLabel = label;
  1125.         }
  1126.         }
  1127.     } else if( aptr->label )
  1128.         DrawLabels = True;
  1129.     return( result );
  1130. }
  1131.  
  1132.  
  1133. void DefineLabels( label )
  1134.     char *label;
  1135. {
  1136.     register Chain __far *chain;
  1137.     register Group __far *group;
  1138.     register Atom __far *aptr;
  1139.     register Label *ptr;
  1140.     register char *cptr;
  1141.     register int len;
  1142.  
  1143.  
  1144.     if( !Database ) return;
  1145.     if( DeleteLabels() ) 
  1146.     return;
  1147.  
  1148.     len = 0;
  1149.     for( cptr=label; *cptr; cptr++ )
  1150.     len++;
  1151.  
  1152.     /* Strip trailing spaces */
  1153.     while( len && cptr[-1]==' ' )
  1154.     {   cptr--;  len--;
  1155.     *cptr = '\0';
  1156.     }
  1157.     if( !len ) return;
  1158.  
  1159.  
  1160.     /* Test for existing label */
  1161.     for( ptr=LabelList; ptr; ptr=ptr->next )
  1162.     if( !strcmp(ptr->label,label) )
  1163.         break;
  1164.  
  1165.     if( !ptr )
  1166.     {   if( FreeLabel )
  1167.     {   ptr = FreeLabel;  FreeLabel = ptr->next;
  1168.     } else if( !(ptr=(Label*)malloc(sizeof(Label))) )
  1169.         FatalRenderError("label");
  1170.  
  1171.     ptr->label = (char*)malloc(len+1);
  1172.     if( !ptr->label ) FatalRenderError("label");
  1173.  
  1174.     cptr = ptr->label;
  1175.     while( *cptr++ = *label++ );
  1176.  
  1177.     ptr->next = LabelList;
  1178.     ptr->refcount = 0;
  1179.     LabelList = ptr;
  1180.     }
  1181.  
  1182.     ForEachAtom
  1183.     if( aptr->flag & SelectFlag )
  1184.     {   aptr->label = ptr;
  1185.         DrawLabels = True;
  1186.         ptr->refcount++;
  1187.     }
  1188. }
  1189.  
  1190.  
  1191. static void DisplayLabels()
  1192. {
  1193.     register Chain __far *chain;
  1194.     register Group __far *group;
  1195.     register Atom __far *aptr;
  1196.     register Label *label;
  1197.     register int col,z;
  1198.  
  1199.     auto char buffer[256];
  1200.  
  1201.  
  1202.     if( !Database )
  1203.     return;
  1204.  
  1205.     if( !UseSlabPlane )
  1206.     {   z = ImageRadius + ZOffset;
  1207.     } else z = SlabValue - 1;
  1208.  
  1209.     ForEachAtom
  1210.     if( aptr->label )
  1211.     {   /* Peform Label Slabbing! */
  1212.         if( !ZValid(aptr->z) )
  1213.         continue;
  1214.  
  1215.         label = (Label*)aptr->label;
  1216.         FormatLabel(chain,group,aptr,label->label,buffer);
  1217.  
  1218.         if( !UseLabelCol )
  1219.         {   /* Depth-cue atom labels */
  1220.         /* col = aptr->col + (ColorDepth*                  */
  1221.         /*       (aptr->z+ImageRadius-ZOffset))/ImageSize; */
  1222.         col = aptr->col + ColourMask;
  1223.         } else col = LabelCol;
  1224.  
  1225.         /* (aptr->z+2) + ((aptr->flag & SphereFlag)?aptr->irad:0); */
  1226.         DisplayString(aptr->x+4,aptr->y,z,buffer,col);
  1227.     }
  1228. }
  1229.  
  1230.  
  1231.  
  1232. #ifdef FUNCPROTO
  1233. /* Function Prototype */
  1234. static void AddDot( Long, Long, Long, int );
  1235. static void CheckVDWDot( Long, Long, Long, int );
  1236. static int TestSolventDot( Long, Long, Long );
  1237. #endif
  1238.  
  1239.  
  1240. void DeleteSurface()
  1241. {
  1242.     register DotStruct __far *ptr;
  1243.     register int shade;
  1244.     register int i;
  1245.  
  1246.     while( DotPtr )
  1247.     {   for( i=0; i<DotPtr->count; i++ )
  1248.     {   shade = Colour2Shade(DotPtr->col[i]);
  1249.         Shade[shade].refcount--;
  1250.     }
  1251.  
  1252.     ptr = DotPtr->next;
  1253.     _ffree( DotPtr );
  1254.     DotPtr = ptr;
  1255.     }
  1256.     DrawDots = False;
  1257. }
  1258.  
  1259.  
  1260. static void AddDot( x, y, z, col )
  1261.     Long x, y, z; int col;
  1262. {
  1263.     register DotStruct __far *ptr;
  1264.     register int i, shade;
  1265.  
  1266.     if( !DotPtr || (DotPtr->count==DotMax) )
  1267.     {   ptr = (DotStruct __far*)_fmalloc(sizeof(DotStruct));
  1268.     if( !ptr ) FatalRenderError("dot surface");
  1269.  
  1270.     ptr->next = DotPtr;
  1271.     ptr->count = 0;
  1272.     DotPtr = ptr;
  1273.     } else ptr = DotPtr;
  1274.  
  1275.     shade = Colour2Shade(col);
  1276.     Shade[shade].refcount++;
  1277.  
  1278.     i = ptr->count++;
  1279.     ptr->col[i] = col;
  1280.     ptr->xpos[i] = x;
  1281.     ptr->ypos[i] = y;
  1282.     ptr->zpos[i] = z;
  1283.     DrawDots = True;
  1284. }
  1285.  
  1286.  
  1287. static void CheckVDWDot( x, y, z, col )
  1288.     Long x, y, z; int col;
  1289. {
  1290.     register Item __far *item;
  1291.     register Atom __far *aptr;
  1292.     register int ix,iy,iz;
  1293.     register int dx,dy,dz;
  1294.     register Long dist;
  1295.     register Long rad;
  1296.     register int i;
  1297.  
  1298.  
  1299.     ix = (int)((x+Offset)*IVoxRatio);
  1300.     iy = (int)((y+Offset)*IVoxRatio);
  1301.     iz = (int)((z+Offset)*IVoxRatio);
  1302.  
  1303.     i = VOXORDER2*ix + VOXORDER*iy + iz;
  1304.     for( item=HashTable[i]; item; item=item->list )
  1305.     if( item->data != Exclude )
  1306.     {   aptr = item->data;
  1307.         if( !ProbeRadius )
  1308.         {   rad = ElemVDWRadius(GetElemNumber(aptr));
  1309.         } else rad = ProbeRadius;
  1310.         rad = rad*rad;
  1311.  
  1312.         /* Optimized Test! */
  1313.         dx = (int)(aptr->xorg - x);
  1314.         if( (dist=(Long)dx*dx) < rad )
  1315.         {   dy = (int)(aptr->yorg - y);
  1316.         if( (dist+=(Long)dy*dy) < rad )
  1317.         {   dz = (int)(aptr->zorg - z);
  1318.             if( (dist+=(Long)dz*dz) < rad )
  1319.             return;
  1320.         }
  1321.         }
  1322.     }
  1323.     AddDot( x, y, z, col );
  1324. }
  1325.  
  1326.  
  1327. static int TestSolventDot( x, y, z )
  1328.     Long x, y, z;
  1329. {
  1330.     register Item __far *item;
  1331.     register Atom __far *aptr;
  1332.     register int lx,ly,lz;
  1333.     register int hx,hy,hz;
  1334.     register int dx,dy,dz;
  1335.     register int ix,iy,iz;
  1336.     register Long dist;
  1337.     register Long rad;
  1338.     register int i;
  1339.  
  1340.     dist = Offset-ProbeRadius;
  1341.     lx = (int)((x+dist)*IVoxRatio);
  1342.     if( lx >= VOXORDER ) return( True );
  1343.     ly = (int)((y+dist)*IVoxRatio);
  1344.     if( ly >= VOXORDER ) return( True );
  1345.     lz = (int)((z+dist)*IVoxRatio);
  1346.     if( lz >= VOXORDER ) return( True );
  1347.  
  1348.     dist = Offset+ProbeRadius;
  1349.     hx = (int)((x+dist)*IVoxRatio);
  1350.     if( hx < 0 ) return( True );
  1351.     hy = (int)((y+dist)*IVoxRatio);
  1352.     if( hy < 0 ) return( True );
  1353.     hz = (int)((z+dist)*IVoxRatio);
  1354.     if( hz < 0 ) return( True );
  1355.  
  1356.     if( lx < 0 ) lx = 0;  if( hx >= VOXORDER ) hx = VOXORDER-1;
  1357.     if( ly < 0 ) ly = 0;  if( hy >= VOXORDER ) hy = VOXORDER-1;
  1358.     if( lz < 0 ) lz = 0;  if( hz >= VOXORDER ) hz = VOXORDER-1;
  1359.  
  1360.     for( ix=lx; ix<=hx; ix++ )
  1361.        for( iy=ly; iy<=hy; iy++ )
  1362.       for( iz=lz; iz<=hz; iz++ )
  1363.       {   i = VOXORDER2*ix + VOXORDER*iy + iz;
  1364.           for( item=HashTable[i]; item; item=item->list )
  1365.           if( item->data != Exclude )
  1366.           {   aptr = item->data;
  1367.               rad = ElemVDWRadius(GetElemNumber(aptr));
  1368.               rad = (rad+ProbeRadius)*(rad+ProbeRadius);
  1369.  
  1370.               /* Optimized Test! */
  1371.               dx = (int)(aptr->xorg - x);
  1372.               if( (dist=(Long)dx*dx) < rad )
  1373.               {   dy = (int)(aptr->yorg - y);
  1374.               if( (dist+=(Long)dy*dy) < rad )
  1375.               {   dz = (int)(aptr->zorg - z);
  1376.                   if( (dist+=(Long)dz*dz) < rad )
  1377.                   return( False );
  1378.               }
  1379.               }
  1380.           }
  1381.       }
  1382.     return( True );
  1383. }
  1384.  
  1385.  
  1386. static void InitElemDots()
  1387. {
  1388.     register int i,size;
  1389.  
  1390.     size = MAXELEMNO*sizeof(ElemDotStruct);
  1391.     ElemDots = (ElemDotStruct __far*)_fmalloc(size);
  1392.     if( !ElemDots ) FatalRenderError("dot vector table");
  1393.  
  1394.     for( i=0; i<MAXELEMNO; i++ )
  1395.     ElemDots[i].count = 0;
  1396. }
  1397.  
  1398.  
  1399. static void AddElemDots( elem, density )
  1400.     int elem, density;
  1401. {
  1402.     register DotVector __far *ptr;
  1403.     register DotVector __far *probe;
  1404.     register Real x, y, z, p, q, xy;
  1405.     register int equat,vert,horz;
  1406.     register int rad,count;
  1407.     register int i,j,k;
  1408.     register int temp;
  1409.  
  1410.   
  1411.     if( SolventDots || !ProbeRadius )
  1412.     {   rad = ElemVDWRadius(elem);
  1413.     } else rad = ProbeRadius;
  1414.  
  1415.     count = (int)(((Long)density*rad*rad)/((Long)250*250));
  1416.     ptr = (DotVector __far*)_fmalloc(count*sizeof(DotVector));
  1417.     if( !ptr ) FatalRenderError("dot vectors");
  1418.  
  1419.     if( SolventDots )
  1420.     {   probe = (DotVector __far*)_fmalloc(count*sizeof(DotVector));
  1421.     if( !probe ) FatalRenderError("probe vectors");
  1422.     temp = rad + ProbeRadius;
  1423.     } else probe = NULL;
  1424.  
  1425.     equat = (int)sqrt(PI*count);
  1426.     if( !(vert=equat>>1) )
  1427.     vert = 1;
  1428.  
  1429.     i = 0;
  1430.     for( j=0; (i<count) && (j<vert); j++ )
  1431.     {   p = (PI*j)/(Real)vert;
  1432.     z = cos(p);  xy = sin(p);
  1433.     horz = (int)(equat*xy);
  1434.     if( !horz ) horz = 1;
  1435.  
  1436.     for( k=0; (i<count) && (k<horz); k++ )
  1437.     {   q = (2.0*PI*k)/(Real)horz;
  1438.         x = xy*sin(q);
  1439.         y = xy*cos(q);
  1440.  
  1441.         ptr[i].dx = (int)(rad*x);
  1442.         ptr[i].dy = (int)(rad*y);
  1443.         ptr[i].dz = (int)(rad*z);
  1444.         if( probe )
  1445.         {   probe[i].dx = (int)(temp*x);
  1446.         probe[i].dy = (int)(temp*y);
  1447.         probe[i].dz = (int)(temp*z);
  1448.         }
  1449.         i++;
  1450.     }
  1451.     }
  1452.     ElemDots[elem].probe = probe;
  1453.     ElemDots[elem].dots = ptr;
  1454.     ElemDots[elem].count = i;
  1455. }
  1456.  
  1457.  
  1458. static void FreeElemDots()
  1459. {
  1460.     register int i;
  1461.  
  1462.     for( i=0; i<MAXELEMNO; i++ )
  1463.     if( ElemDots[i].count )
  1464.         _ffree( ElemDots[i].dots );
  1465.     _ffree( ElemDots );
  1466. }
  1467.  
  1468.  
  1469. void CalculateSurface( density )
  1470.     int density;
  1471. {
  1472.     register DotVector __far *probe;
  1473.     register DotVector __far *ptr;
  1474.     register Chain __far *chain;
  1475.     register Group __far *group;
  1476.     register Atom __far *aptr;
  1477.     register int i,count;
  1478.     register int elem;
  1479.  
  1480.     if( !Database )
  1481.     return;
  1482.  
  1483.     DeleteSurface();
  1484.     ResetVoxelData();
  1485.  
  1486.     InitElemDots();
  1487.     CreateVoxelData( AllAtomFlag );
  1488.     VoxelsClean = False;
  1489.  
  1490.     ForEachAtom
  1491.     if( aptr->flag & SelectFlag )
  1492.     {   elem = GetElemNumber(aptr);
  1493.         if( !ElemDots[elem].count )
  1494.         AddElemDots(elem,density);
  1495.  
  1496.         Exclude = aptr;
  1497.         ptr = ElemDots[elem].dots;
  1498.         probe = ElemDots[elem].probe;
  1499.         count = ElemDots[elem].count;
  1500.         if( SolventDots )
  1501.         {   for( i=0; i<count; i++ )
  1502.             if( TestSolventDot( aptr->xorg + probe[i].dx,
  1503.                     aptr->yorg + probe[i].dy,
  1504.                     aptr->zorg + probe[i].dz ) )
  1505.             AddDot( aptr->xorg + ptr[i].dx,
  1506.                 aptr->yorg + ptr[i].dy,
  1507.                 aptr->zorg + ptr[i].dz,
  1508.                 aptr->col );
  1509.         } else 
  1510.         for( i=0; i<count; i++ )
  1511.             CheckVDWDot( aptr->xorg + ptr[i].dx,
  1512.                  aptr->yorg + ptr[i].dy,
  1513.                  aptr->zorg + ptr[i].dz,
  1514.                  aptr->col);
  1515.     }
  1516.  
  1517.     FreeElemDots();
  1518. }
  1519.  
  1520.  
  1521. static void DisplaySurface()
  1522. {
  1523.     register DotStruct __far *ptr;
  1524.     register int xi,yi,zi;
  1525.     register Real x,y,z;
  1526.     register int i;
  1527.  
  1528.     for( ptr=DotPtr; ptr; ptr=ptr->next )
  1529.     for( i=0; i<ptr->count; i++ )
  1530.     {   x = ptr->xpos[i];  
  1531.         y = ptr->ypos[i];  
  1532.         z = ptr->zpos[i];
  1533.  
  1534.         xi = (int)(x*MatX[0]+y*MatX[1]+z*MatX[2])+XOffset;
  1535.         if( XValid(xi) )
  1536.         {   yi = (int)(x*MatY[0]+y*MatY[1]+z*MatY[2])+YOffset;
  1537.         if( YValid(yi) )
  1538.         {   zi = (int)(x*MatZ[0]+y*MatZ[1]+z*MatZ[2])+ZOffset;
  1539.             if( ZValid(zi) ) 
  1540.             PlotDeepPoint(xi,yi,zi,ptr->col[i]);
  1541.         }
  1542.         }
  1543.     }
  1544. }
  1545.  
  1546.  
  1547. static void DisplayBoxes()
  1548. {
  1549.     register Real cosa, cosb, cosg;
  1550.     register Real sina, sinb, sing;
  1551.     register Real lena, lenb, lenc;
  1552.     register Real tmpx, tmpy, tmpz;
  1553.     register Real temp;
  1554.  
  1555.     register int xorg, yorg, zorg;
  1556.     register int dxx,dxy,dxz;
  1557.     register int dyx,dyy,dyz;
  1558.     register int dzx,dzy,dzz;
  1559.     register int x, y, z;
  1560.  
  1561.  
  1562.     if( DrawAxes  || DrawBoundBox )
  1563.     {   dxx = (int)(MaxX*MatX[0]);
  1564.     dxy = (int)(MaxX*MatY[0]);
  1565.     dxz = (int)(MaxX*MatZ[0]);
  1566.  
  1567.     dyx = (int)(MaxY*MatX[1]);
  1568.     dyy = (int)(MaxY*MatY[1]);
  1569.     dyz = (int)(MaxY*MatZ[1]);
  1570.  
  1571.     dzx = (int)(MaxZ*MatX[2]);
  1572.     dzy = (int)(MaxZ*MatY[2]);
  1573.     dzz = (int)(MaxZ*MatZ[2]);
  1574.  
  1575.     if( DrawAxes )
  1576.     {   /* Line (MinX,0,0) to (MaxX,0,0) */
  1577.         ClipTwinLine(XOffset-dxx,YOffset-dxy,ZOffset-dxz, 
  1578.              XOffset+dxx,YOffset+dxy,ZOffset+dxz,BoxCol,BoxCol);
  1579.  
  1580.         /* Line (0,MinY,0) to (0,MaxY,0) */
  1581.         ClipTwinLine(XOffset-dyx,YOffset-dyy,ZOffset-dyz, 
  1582.              XOffset+dyx,YOffset+dyy,ZOffset+dyz,BoxCol,BoxCol);
  1583.  
  1584.         /* Line (0,0,MinZ) to (0,0,MaxZ) */
  1585.         ClipTwinLine(XOffset-dzx,YOffset-dzy,ZOffset-dzz, 
  1586.              XOffset+dzx,YOffset+dzy,ZOffset+dzz,BoxCol,BoxCol);
  1587.     }
  1588.  
  1589.     if( DrawBoundBox )
  1590.     {   /* Line (MinX,MinY,MinZ) to (MaxX,MinY,MinZ) */
  1591.         x=XOffset-dyx-dzx;  y=YOffset-dyy-dzy;  z=ZOffset-dyz-dzz;
  1592.         ClipTwinLine(x-dxx,y-dxy,z-dxz,x+dxx,y+dxy,z+dxz,BoxCol,BoxCol);
  1593.  
  1594.         /* Line (MaxX,MinY,MinZ) to (MaxX,MaxY,MinZ) */
  1595.         x=XOffset+dxx-dzx;  y=YOffset+dxy-dzy;  z=ZOffset+dxz-dzz;
  1596.         ClipTwinLine(x-dyx,y-dyy,z-dyz,x+dyx,y+dyy,z+dyz,BoxCol,BoxCol);
  1597.  
  1598.         /* Line (MaxX,MaxY,MinZ) to (MinX,MaxY,MinZ) */
  1599.         x=XOffset+dyx-dzx;  y=YOffset+dyy-dzy;  z=ZOffset+dyz-dzz;
  1600.         ClipTwinLine(x+dxx,y+dxy,z+dxz,x-dxx,y-dxy,z-dxz,BoxCol,BoxCol);
  1601.  
  1602.         /* Line (MinX,MaxY,MinZ) to (MinX,MinY,MinZ) */
  1603.         x=XOffset-dxx-dzx;  y=YOffset-dxy-dzy;  z=ZOffset-dxz-dzz;
  1604.         ClipTwinLine(x+dyx,y+dyy,z+dyz,x-dyx,y-dyy,z-dyz,BoxCol,BoxCol);
  1605.  
  1606.  
  1607.         /* Line (MinX,MinY,MinZ) to (MinX,MinY,MaxZ) */
  1608.         x=XOffset-dxx-dyx;  y=YOffset-dxy-dyy;  z=ZOffset-dxz-dyz;
  1609.         ClipTwinLine(x-dzx,y-dzy,z-dzz,x+dzx,y+dzy,z+dzz,BoxCol,BoxCol);
  1610.  
  1611.         /* Line (MaxX,MinY,MinZ) to (MaxX,MinY,MaxZ) */
  1612.         x=XOffset+dxx-dyx;  y=YOffset+dxy-dyy;  z=ZOffset+dxz-dyz;
  1613.         ClipTwinLine(x-dzx,y-dzy,z-dzz,x+dzx,y+dzy,z+dzz,BoxCol,BoxCol);
  1614.  
  1615.         /* Line (MaxX,MaxY,MinZ) to (MaxX,MaxY,MaxZ) */
  1616.         x=XOffset+dxx+dyx;  y=YOffset+dxy+dyy;  z=ZOffset+dxz+dyz;
  1617.         ClipTwinLine(x-dzx,y-dzy,z-dzz,x+dzx,y+dzy,z+dzz,BoxCol,BoxCol);
  1618.  
  1619.         /* Line (MinX,MaxY,MinZ) to (MinX,MaxY,MaxZ) */
  1620.         x=XOffset-dxx+dyx;  y=YOffset-dxy+dyy;  z=ZOffset-dxz+dyz;
  1621.         ClipTwinLine(x-dzx,y-dzy,z-dzz,x+dzx,y+dzy,z+dzz,BoxCol,BoxCol);
  1622.  
  1623.  
  1624.         /* Line (MinX,MinY,MaxZ) to (MaxX,MinY,MaxZ) */
  1625.         x=XOffset-dyx+dzx;  y=YOffset-dyy+dzy;  z=ZOffset-dyz+dzz;
  1626.         ClipTwinLine(x-dxx,y-dxy,z-dxz,x+dxx,y+dxy,z+dxz,BoxCol,BoxCol);
  1627.  
  1628.         /* Line (MaxX,MinY,MaxZ) to (MaxX,MaxY,MaxZ) */
  1629.         x=XOffset+dxx+dzx;  y=YOffset+dxy+dzy;  z=ZOffset+dxz+dzz;
  1630.         ClipTwinLine(x-dyx,y-dyy,z-dyz,x+dyx,y+dyy,z+dyz,BoxCol,BoxCol);
  1631.  
  1632.         /* Line (MaxX,MaxY,MaxZ) to (MinX,MaxY,MaxZ) */
  1633.         x=XOffset+dyx+dzx;  y=YOffset+dyy+dzy;  z=ZOffset+dyz+dzz;
  1634.         ClipTwinLine(x+dxx,y+dxy,z+dxz,x-dxx,y-dxy,z-dxz,BoxCol,BoxCol);
  1635.  
  1636.         /* Line (MinX,MaxY,MaxZ) to (MinX,MinY,MaxZ) */
  1637.         x=XOffset-dxx+dzx;  y=YOffset-dxy+dzy;  z=ZOffset-dxz+dzz;
  1638.         ClipTwinLine(x+dyx,y+dyy,z+dyz,x-dyx,y-dyy,z-dyz,BoxCol,BoxCol);
  1639.     }
  1640.     }
  1641.  
  1642.     if( DrawUnitCell )
  1643.     {   /* Calculate Unit Cell! */
  1644.     lena =  250.0*InfoCellA;
  1645.     lenb =  250.0*InfoCellB;
  1646.     lenc = -250.0*InfoCellC;
  1647.  
  1648.     cosa = cos(InfoCellAlpha);  sina = sin(InfoCellAlpha);
  1649.     cosb = cos(InfoCellBeta);   sinb = sin(InfoCellBeta);
  1650.     cosg = cos(InfoCellGamma);  sing = sin(InfoCellGamma);
  1651.  
  1652.     temp = cosa*cosa + cosb*cosb + cosg*cosg - 2.0*cosa*cosb*cosg;
  1653.     tmpx = cosb; 
  1654.     tmpy = (cosa - cosb*cosg)/sing;
  1655.     tmpz = sqrt(1.0-temp)/sing;
  1656.  
  1657.     dxx = (int)(lena*MatX[0]);
  1658.     dxy = (int)(lena*MatY[0]);
  1659.     dxz = (int)(lena*MatZ[0]);
  1660.  
  1661.     dyx = (int)(lenb*(cosg*MatX[0] + sing*MatX[1]));
  1662.     dyy = (int)(lenb*(cosg*MatY[0] + sing*MatY[1]));
  1663.     dyz = (int)(lenb*(cosg*MatZ[0] + sing*MatZ[1]));
  1664.  
  1665.     dzx = (int)(lenc*(tmpx*MatX[0] + tmpy*MatX[1] + tmpz*MatX[2]));
  1666.     dzy = (int)(lenc*(tmpx*MatY[0] + tmpy*MatY[1] + tmpz*MatY[2]));
  1667.     dzz = (int)(lenc*(tmpx*MatZ[0] + tmpy*MatZ[1] + tmpz*MatZ[2]));
  1668.  
  1669.     xorg = XOffset - (int)(OrigCX*MatX[0]+OrigCY*MatX[1]+OrigCZ*MatX[2]);
  1670.     yorg = YOffset - (int)(OrigCX*MatY[0]+OrigCY*MatY[1]+OrigCZ*MatY[2]);
  1671.     zorg = ZOffset + (int)(OrigCX*MatZ[0]+OrigCY*MatZ[1]+OrigCZ*MatZ[2]);
  1672.  
  1673.  
  1674.     /* Draw Unit Cell! */
  1675.     x = xorg;
  1676.     y = yorg;
  1677.     z = zorg;
  1678.     ClipTwinLine(x,y,z,x+dxx,y+dxy,z+dxz,BoxCol,BoxCol);
  1679.     ClipTwinLine(x,y,z,x+dyx,y+dyy,z+dyz,BoxCol,BoxCol);
  1680.     ClipTwinLine(x,y,z,x+dzx,y+dzy,z+dzz,BoxCol,BoxCol);
  1681.  
  1682.     x = xorg + dxx + dyx;
  1683.     y = yorg + dxy + dyy;
  1684.     z = zorg + dxz + dyz;
  1685.     ClipTwinLine(x,y,z,x-dxx,y-dxy,z-dxz,BoxCol,BoxCol);
  1686.     ClipTwinLine(x,y,z,x-dyx,y-dyy,z-dyz,BoxCol,BoxCol);
  1687.     ClipTwinLine(x,y,z,x+dzx,y+dzy,z+dzz,BoxCol,BoxCol);
  1688.  
  1689.     x = xorg + dxx + dzx;
  1690.     y = yorg + dxy + dzy;
  1691.     z = zorg + dxz + dyz;
  1692.     ClipTwinLine(x,y,z,x-dxx,y-dxy,z-dxz,BoxCol,BoxCol);
  1693.     ClipTwinLine(x,y,z,x+dyx,y+dyy,z+dyz,BoxCol,BoxCol);
  1694.     ClipTwinLine(x,y,z,x-dzx,y-dzy,z-dzz,BoxCol,BoxCol);
  1695.  
  1696.     x = xorg + dyx + dzx;
  1697.     y = yorg + dyy + dzy;
  1698.     z = zorg + dyz + dzz;
  1699.     ClipTwinLine(x,y,z,x+dxx,y+dxy,z+dxz,BoxCol,BoxCol);
  1700.     ClipTwinLine(x,y,z,x-dyx,y-dyy,z-dyz,BoxCol,BoxCol);
  1701.     ClipTwinLine(x,y,z,x-dzx,y-dzy,z-dzz,BoxCol,BoxCol);
  1702.     }
  1703. }
  1704.  
  1705.  
  1706. static void DisplaySelected()
  1707. {
  1708.     register Atom __far *s, __far *d;
  1709.     register Chain __far *chain;
  1710.     register Group __far *group;
  1711.     register Bond __far *bptr;
  1712.     register Atom __far *aptr;
  1713.     register int irad,sc,dc;
  1714.     register int col;
  1715.  
  1716.     irad = (int)(Scale*20);
  1717.  
  1718.     if( irad>0 )
  1719.     {   ForEachBond
  1720.     {   s = bptr->srcatom;  
  1721.         col = (s->flag&SelectFlag)? 1 : 0;
  1722.         sc = Shade2Colour(col);
  1723.  
  1724.         d = bptr->dstatom;  
  1725.         col = (d->flag&SelectFlag)? 1 : 0;
  1726.         dc = Shade2Colour(col);
  1727.         ClipCylinder(s->x,s->y,s->z,sc,d->x,d->y,d->z,dc,irad);
  1728.     }
  1729.     } else ForEachBond
  1730.     {   s = bptr->srcatom;  
  1731.         col = (s->flag&SelectFlag)? 1 : 0;
  1732.         sc = Shade2Colour(col);
  1733.  
  1734.         d = bptr->dstatom;  
  1735.         col = (d->flag&SelectFlag)? 1 : 0;
  1736.         dc = Shade2Colour(col);
  1737.         ClipTwinLine(s->x,s->y,s->z,d->x,d->y,d->z,
  1738.              sc+ColourMask,dc+ColourMask);
  1739.     }
  1740.  
  1741.  
  1742.     irad = (int)(Scale*50);
  1743.     ForEachAtom
  1744.     if( aptr->flag&NonBondFlag )
  1745.     {   col = Shade2Colour( (aptr->flag&SelectFlag)? 1 : 0 );
  1746.         ClipSphere(aptr->x,aptr->y,aptr->z,irad,col);
  1747.     }
  1748. }
  1749.  
  1750.  
  1751. void DrawFrame()
  1752. {
  1753.     register Chain __far *chain;
  1754.  
  1755.     if( !Database ) 
  1756.     return;
  1757.  
  1758.     ClearBuffers();
  1759.  
  1760.     if( UseSlabPlane )
  1761.     {   SlabValue = (int)(DialValue[7]*ImageRadius)+ZOffset;
  1762.     SlabInten = (int)(ColourMask*TwoOverRootSix);
  1763.     SliceValue = SlabValue+16;
  1764.     UseClipping = True;
  1765.     } else UseClipping = UseScreenClip;
  1766.  
  1767. #ifdef IBMPC
  1768.     /* Lock Buffers into Memory */
  1769.     FBuffer = (Pixel __huge*)GlobalLock(FBufHandle);
  1770.     DBuffer = (short __huge*)GlobalLock(DBufHandle);
  1771. #endif
  1772.  
  1773.     if( !DisplayMode )
  1774.     {   if( UseShadow && DrawAtoms )
  1775.         if( !VoxelsClean )
  1776.         CreateVoxelData( SphereFlag );
  1777.  
  1778.     if( DrawAtoms ) 
  1779.         DisplaySpaceFill();
  1780.  
  1781.     if( !UseSlabPlane || (SlabMode != SlabSection) )
  1782.     {   if( DrawBonds ) 
  1783.         DisplayWireFrame();
  1784.  
  1785.         if( DrawRibbon )
  1786.         for( chain=Database->clist; chain; chain=chain->cnext )
  1787.             if( chain->glist )
  1788.             DisplayRibbon( chain );
  1789.  
  1790.         if( DrawDots ) DisplaySurface();
  1791.         if( DrawLabels ) DisplayLabels();
  1792.         DisplayHBonds( Database->slist, SSBondMode );
  1793.         DisplayHBonds( Database->hlist, HBondMode );
  1794.         DisplayBackBone();
  1795.     }
  1796.     } else DisplaySelected();
  1797.     DisplayBoxes();
  1798.  
  1799. #ifdef IBMPC
  1800.     /* Unlock Buffers */
  1801.     GlobalUnlock(FBufHandle);
  1802.     GlobalUnlock(DBufHandle);
  1803. #endif
  1804.     DBClear = False;
  1805.     FBClear = False;
  1806. }
  1807.  
  1808.  
  1809.  
  1810. #ifdef FUNCPROTO
  1811. /* Function Prototype */
  1812. static void TestAtomProximity( Atom __far *, int, int );
  1813. #endif
  1814.  
  1815.  
  1816. static void TestAtomProximity( ptr, xpos, ypos )
  1817.     Atom __far *ptr;
  1818.     int xpos, ypos;
  1819. {
  1820.     register Long dist;
  1821.     register int dx,dy;
  1822.  
  1823.     if( UseSlabPlane && (ptr->z>SlabValue) )
  1824.     return;
  1825.  
  1826.     dx = ptr->x - xpos;
  1827.     dy = ptr->y - ypos;
  1828.  
  1829.     dist = (Long)dx*dx + (Long)dy*dy;
  1830.  
  1831.     if( IdentFound )
  1832.     {   if( dist==IdentDist )
  1833.     {   if( ptr->z<IdentDepth )
  1834.         return;
  1835.     } else if( dist>IdentDist ) 
  1836.         return;
  1837.     }
  1838.  
  1839.     IdentDepth = ptr->z;
  1840.     IdentFound = True;
  1841.     IdentDist = dist;
  1842.     QAtom = ptr;
  1843. }
  1844.  
  1845. void IdentifyAtom( xpos, ypos )
  1846.     int xpos, ypos;
  1847. {
  1848.     register int rad, wide, dpth;
  1849.     register int new, dx, dy, dz;
  1850.     register Chain __far *chain;
  1851.     register Group __far *group;
  1852.     register HBond __far *hptr;
  1853.     register Atom  __far *aptr;
  1854.     register Bond __far *bptr;
  1855.     register char *str;
  1856.     char buffer[40];
  1857.  
  1858.     /* Reset Search */
  1859.     QChain = (void __far*)0;
  1860.     QGroup = (void __far*)0;
  1861.     QAtom = (void __far*)0;
  1862.     IdentFound = False;
  1863.  
  1864.     if( !DisplayMode )
  1865.     {   if( !UseSlabPlane || (SlabMode != SlabSection) )
  1866.     {   if( DrawBonds )
  1867.         ForEachBond
  1868.             if( bptr->flag&DrawBondFlag )
  1869.             {   TestAtomProximity(bptr->srcatom,xpos,ypos);
  1870.             TestAtomProximity(bptr->dstatom,xpos,ypos);
  1871.             }
  1872.  
  1873.         ForEachBack
  1874.         if( bptr->flag&DrawBondFlag )
  1875.         {   TestAtomProximity(bptr->srcatom,xpos,ypos);
  1876.             TestAtomProximity(bptr->dstatom,xpos,ypos);
  1877.         }
  1878.  
  1879.         for( hptr=Database->hlist; hptr; hptr=hptr->hnext )
  1880.         if( hptr->flag )
  1881.         {   if( HBondMode )
  1882.             {   TestAtomProximity(hptr->srcCA,xpos,ypos);
  1883.             TestAtomProximity(hptr->dstCA,xpos,ypos);
  1884.             } else
  1885.             {   TestAtomProximity(hptr->src,xpos,ypos);
  1886.             TestAtomProximity(hptr->dst,xpos,ypos);
  1887.             }
  1888.         }
  1889.  
  1890.         for( hptr=Database->slist; hptr; hptr=hptr->hnext )
  1891.         if( hptr->flag )
  1892.         {   if( HBondMode )
  1893.             {   TestAtomProximity(hptr->srcCA,xpos,ypos);
  1894.             TestAtomProximity(hptr->dstCA,xpos,ypos);
  1895.             } else
  1896.             {   TestAtomProximity(hptr->src,xpos,ypos);
  1897.             TestAtomProximity(hptr->dst,xpos,ypos);
  1898.             }
  1899.         }
  1900.     }
  1901.  
  1902.     ForEachAtom
  1903.     {   /* Identify bond! */
  1904.         if( aptr == QAtom )
  1905.         {   QChain = chain;
  1906.         QGroup = group;
  1907.         }
  1908.  
  1909.         if( aptr->flag & SphereFlag )
  1910.         {   dy = AbsFun(aptr->y-ypos);
  1911.         if( dy>aptr->irad ) continue;
  1912.         rad = LookUp[aptr->irad][dy];
  1913.         dx = AbsFun(aptr->x-xpos);
  1914.         if( dx>rad ) continue;
  1915.  
  1916.         new = False;
  1917.         dpth = aptr->z+LookUp[rad][dx];
  1918.         if( UseSlabPlane && (aptr->z+rad>=SlabValue) )
  1919.         {   dz = SlabValue-aptr->z;
  1920.             if( SlabMode && (dz >= -rad) )
  1921.             {   wide = LookUp[aptr->irad][AbsFun(dz)];
  1922.             if( (dy<=wide) && (dx<=(int)(LookUp[wide][dy])) )
  1923.             {   if( SlabMode == SlabFinal )
  1924.                 {   dpth = SliceValue;
  1925.                 new = True;
  1926.                 } else if( SlabMode == SlabHollow )
  1927.                 {   dpth = aptr->z-LookUp[rad][dx];
  1928.                 new = !IdentFound || (dpth>IdentDepth);
  1929.                 } else if( SlabMode != SlabHalf )
  1930.                 {   /* SlabClose, SlabSection */
  1931.                 dpth = dx*dx+dy*dy+dz*dz+SliceValue;
  1932.                 if( IdentFound )
  1933.                 {   new = (IdentDepth<SliceValue) 
  1934.                       || (dpth<IdentDepth);
  1935.                 } else new=True;
  1936.                 }
  1937.             } else if( (dz>0) && (SlabMode!=SlabSection) )
  1938.                 new = !IdentFound || (dpth>IdentDepth);
  1939.             }
  1940.         } else if( !UseSlabPlane || (SlabMode != SlabSection) )
  1941.             new = !IdentFound || IdentDist || (dpth>IdentDepth);
  1942.  
  1943.         if( new )
  1944.         {   IdentFound = True;
  1945.             IdentDepth = dpth;
  1946.             IdentDist = 0;
  1947.  
  1948.             QChain = chain;
  1949.             QGroup = group;
  1950.             QAtom = aptr;
  1951.         }
  1952.         } 
  1953.     }
  1954.     } else /* Display Mode */
  1955.     {   ForEachAtom
  1956.     {   TestAtomProximity(aptr,xpos,ypos);
  1957.         /* Identify bond! */
  1958.         if( aptr == QAtom )
  1959.         {   QChain = chain;
  1960.         QGroup = group;
  1961.         }
  1962.     }
  1963.     }
  1964.  
  1965.  
  1966.     if( IdentFound && (IdentDist<50) )
  1967.     {   if( CommandActive )
  1968.         WriteChar('\n');
  1969.     CommandActive = False;
  1970.  
  1971.     WriteString("Atom: ");
  1972.     str = ElemDesc[QAtom->refno];
  1973.     if( str[0]!=' ' )   WriteChar(str[0]);
  1974.     WriteChar(str[1]);  WriteChar(str[2]);
  1975.     if( str[3]!=' ' )   WriteChar(str[3]);
  1976.  
  1977.     sprintf(buffer," %d  ",QAtom->serno);
  1978.     WriteString(buffer);
  1979.  
  1980.     str = Residue[QGroup->refno];
  1981.     if( QAtom->flag&HeteroFlag )
  1982.     {   WriteString("Hetero: ");
  1983.     } else WriteString("Group: ");
  1984.  
  1985.     if( str[0]!=' ' )  WriteChar(str[0]);
  1986.     WriteChar(str[1]); WriteChar(str[2]);
  1987.  
  1988.     sprintf(buffer," %d",QGroup->serno);
  1989.     WriteString(buffer);
  1990.  
  1991.     if( QChain->ident!=' ' )
  1992.     {   WriteString("  Chain: ");
  1993.         WriteChar(QChain->ident);
  1994.     }
  1995.     WriteChar('\n');
  1996.     
  1997.     } else /* Reset Pick Atom! */
  1998.     {   QChain = (void __far*)0;
  1999.     QGroup = (void __far*)0;
  2000.     QAtom = (void __far*)0;
  2001.     }
  2002. }
  2003.  
  2004.  
  2005. void SetStereoMode( enable )
  2006.     int enable;
  2007. {
  2008.     StereoView = ViewLeft;
  2009.     UseStereo = enable;
  2010. }
  2011.  
  2012.  
  2013. void ResetRenderer()
  2014. {
  2015.     DeleteSurface();
  2016.     SolventDots = False;
  2017.     ProbeRadius = 0;
  2018.  
  2019.     DrawAtoms = False;  MaxAtomRadius = 0;
  2020.     DrawBonds = False;  MaxBondRadius = 0;
  2021.     DrawRibbon = False; DrawDots = False;
  2022.     DrawLabels = False;
  2023.     ResetLabels();
  2024.  
  2025.     SlabMode = SlabClose;
  2026.     UseSlabPlane = False;
  2027.     UseLabelCol = False;
  2028.     UseShadow = False;
  2029.  
  2030.     SSBondMode = False;
  2031.     HBondMode = False;
  2032.     DisplayMode = 0;
  2033.  
  2034.     DrawBoundBox = False;
  2035.     DrawUnitCell = False;
  2036.     DrawAxes = False;
  2037.  
  2038.     SetStereoMode(False);
  2039. }
  2040.  
  2041.  
  2042. void InitialiseRenderer()
  2043. {
  2044.     register Real radius2;
  2045.     register Byte __far *ptr;
  2046.     register int index,rad;
  2047.     register int maxval;
  2048.  
  2049.     FBuffer = (void __huge*)0;  
  2050.     DBuffer = (void __huge*)0;
  2051.     IBuffer = (void __far*)0;   
  2052.     YBucket = (void __far*)0;
  2053.  
  2054. #if defined(IBMPC) || defined(APPLEMAC)
  2055.     FBufHandle = NULL;
  2056.     DBufHandle = NULL;
  2057. #endif
  2058.  
  2059. #if defined(IBMPC) || defined(APPLEMAC)
  2060.     /* Allocate tables on FAR heaps */ 
  2061.     Array = (Byte __far*)_fmalloc(7261*sizeof(Byte));
  2062.     LookUp = (Byte __far* __far*)_fmalloc(120*sizeof(Byte __far*));
  2063.     HashTable = (void __far* __far*)_fmalloc(VOXSIZE*sizeof(void __far*));
  2064.     ColConst = (Card __far*)_fmalloc(120*sizeof(Card));
  2065.     
  2066.     if( !Array || !LookUp || !HashTable || !ColConst )
  2067.     FatalRenderError("tables");
  2068. #endif
  2069.  
  2070.     ptr = Array;
  2071.     for( rad=0; rad<120; rad++ )
  2072.     {   radius2 = rad*rad;
  2073.     LookUp[rad] = ptr;
  2074.     for( index=0; index<=rad; index++ )
  2075.         *ptr++ = isqrt( (Card)(radius2-index*index) );
  2076.  
  2077.     maxval = (int)(RootSix*rad)+2;
  2078.     ColConst[rad] = ((Card)ColourDepth<<ColBits)/maxval;
  2079.     }
  2080.  
  2081.     DotPtr = (void __far*)0;
  2082.     FreeItem = (void __far*)0;
  2083.     FreeLabel = (void*)0;
  2084.     LabelList = (void*)0;
  2085.  
  2086.     VoxelsClean = False;
  2087.     VoxelsDone = False;
  2088.     BucketFlag = False;
  2089.     RayCount = 0;
  2090.  
  2091.     ResetRenderer();
  2092.     ReSizeScreen();
  2093. }
  2094.